<?php
require_once(PATH_GI_HELPER . "Html.php");
class Helper_Tpl{

	public $left_delimiter = '<?';
	public $right_delimiter = '?>';
	public $view_dir = "";
	public $template_dir = "";
	public $compile_dir = "";
	public $templateExt = ".tpl.php";
	public $dir_list = array("Admin");
	private  $data = array();
	public $showDebug = null;

	public function assign($varname,$value){
		$this->data[$varname] = $value;
	}
	
	public function get($name=null){
		if($name === null){ 
			return $this->data;
		}
		return isset($this->data[$name]) ? $this->data[$name] : null;
	}

	
	protected function compile($tpl_filename){
		
		$tpl_dir =  $this->template_dir == "" ? $this->getTemplateDIR() : $this->template_dir;
		
		$tpl_filename == "" &&  $tpl_filename = $this->getTemplateName();

		//获取文件的绝对地址
		$tpl_full_path = $this->view_dir . $tpl_dir 
				. DIRECTORY_SEPARATOR . $tpl_filename . $this->templateExt;
		$tpl_path = $tpl_dir 
				. DIRECTORY_SEPARATOR . $tpl_filename;
		
		if (!file_exists($tpl_full_path)) {
			throw new GiException("模板文件没找到! $tpl_full_path ");
		}
		//获取文件的修改时间
		$tpl_update_time = filemtime($tpl_full_path);

		//生产编译后的文件名
		$compiled_name = str_replace(array('/',"\\","."),"_",$tpl_path);
		$compiled_name_extension = $tpl_update_time.'.php';
		$compiled_path = PATH_CACHE . $this->compile_dir ;
		
		if(!file_exists($compiled_path)){
			mkdir($compiled_path);
		}
		
		$compiled_full_path = $compiled_path
				. DIRECTORY_SEPARATOR . $compiled_name . "." . $compiled_name_extension ;
		
		//如果编译后的文件存在，则直接返回
		if (file_exists($compiled_full_path)) {
			_trace("Templates $tpl_filename Use Cache!","TPL");
			return $compiled_full_path;
		}else {
			_trace("Templates $tpl_filename Updated!","TPL");
			@Helper_FileSystem::rm("{$compiled_path}{$compiled_name}.*.php");
		}

		//完成模版替换
		$left_delimiter = addcslashes($this->left_delimiter,"?*.+");
		$right_delimiter = addcslashes($this->right_delimiter,"?*.+");
		
		$pattern[0] = "'{$left_delimiter}(.*){$right_delimiter}'Uism";
		$pattern[1] = "'{$left_delimiter}php =(.*)$right_delimiter'Uism";
		$pattern[2] = "'{$left_delimiter}php include\(((\"|\').+(\"|\'))\)$right_delimiter'Uism";

			
		$replace[0] = "<?php $1?>";
		$replace[1] = "<?php echo $1?>";
		$replace[2] = "<?php \$this->display($1)?>";

		$tpl_content = file_get_contents($tpl_full_path);
		$tpl_content = preg_replace($pattern,$replace,$tpl_content);

		//存储文件
		file_put_contents($compiled_full_path,$tpl_content);

		return $compiled_full_path;

	}

	public function display($tpl_filename = ""){
		$this->addExtraData();
		extract($this->data); 
		$tpl_file = $this->compile($tpl_filename);
		include($tpl_file);
	}

	public function __destruct(){
		$this->displayDebugInfo();
	}

	protected function displayDebugInfo(){
		if($this->showDebug === null){
			$this->showDebug = C('DEBUG_MODE');
		}
		if ($this->showDebug === false || $this->showDebug === 0) {
			return;
		}
		echo "
			<script>
				function show_debug(el){
					var debug_info = document.getElementById(el);
					if('none' == debug_info.style.display){
						debug_info.style.display='block';
					}else {
						debug_info.style.display='none';
					}
				}
			</script>
			<style>
			#debug_button,
			#debug_info *
			{font-size:10px;	font-family:Verdana; margin:0px; padding 0px;}
			</style>
			";
		
		echo "<div id='debug_button' ><a href='javascript:show_debug(\"debug_info\")'>DEBUG</a></div>";
		echo "<div id='debug_info' style='display:none'>";
		
		$this->_debugInfo("TRACE", _trace());
		$this->_debugInfo("SESSION", $_SESSION);
		$this->_debugInfo("GET", $_GET);
		$this->_debugInfo("POST", $_POST);
		$defined = get_defined_constants(true);
		$this->_debugInfo("DEFINED", $defined['user']);
		$this->_debugInfo("TPL_VARS", $this->data);
		$this->_debugInfo("CONFIG", C());
		
		echo "</div>";
	}
	
	private function _debugInfo($name,$data){
		$id = '_debug_' . md5($name);
		echo "<div><h3><a href='javascript:show_debug(\"$id\")'>$name</a></h3>";
		echo "<div id='$id' style='display:none'><pre>";
		print_r($data);
		echo "</pre></div>";
		echo "</div>";
		echo "</ hr>";
	}
	
	protected function url($action="",$parameter=""){
		$info = $this->getCtlAndActionName();
    	return _url($info['ctl'],$action,$parameter);
	}
	/**
	 * 
	 * Get the template name according to the controller and action 's name
	 * 
	 * Moreove,If we found the First Word of the controller, is in the list we specifyed, Like Admin,Front, we will treat it as the default dir of this template.
	 * 
	 * To use this function, you must be sure that your template is named regularly.
	 * 
	 * 
	 * @return string
	 */
	protected function getTemplateName(){

		$info = $this->getCtlAndActionName();
		
		foreach ($this->dir_list as $dir){
			if (strpos($info['ctl'],$dir) === 0) {
				//If we don't specify the directory of template, we use the one we find in the controller.
				$ctl = substr($info['ctl'],strlen($dir));
				if (empty($this->template_dir)) {
					$template_dir = $dir;
				} else {
					$template_dir = "";
				}
				
				break;
			}else{
				$ctl = $info['ctl'];
				$template_dir = "";
			}
			
		};
		return  $ctl . "_" . $info['action'];
	}
	/**
	 * 
	 * Get the template directory according to the controller 's name
	 * If we found the First Word of the controller, is in the list we specifyed, Like Admin,Front, we will trate it as the default dir of this template.
	 * 
	 * To use this function, you must be sure that your template DIR is named regularly.
	 * 
	 * 
	 * @return string
	 */
	protected function getTemplateDIR(){
		
		$info = $this->getCtlAndActionName();
		foreach ($this->dir_list as $dir){
			if (strpos($info['ctl'],$dir) === 0) {
				$ctl = substr($info['ctl'],strlen($dir));
				
				//If we don't specify the directory of template, we use the one we find in the controller.
				if (empty($this->template_dir)) {
					$template_dir = $dir;
				} else {
					$template_dir = "";
				}
				
				break;
			}
			
		}
		empty($template_dir) && $template_dir = "Front";
		return  $template_dir;
	}	
	protected function addExtraData(){
		//Ctl and Action's name
		$data['TPL'] = $this->getCtlAndActionName();
		$dir = $this->template_dir == "" ? $this->getTemplateDIR() : $this->template_dir;
		$data['TPL']["url"] = URL_WEB . "View/". $dir . "/";
		//merge the data
		$this->data = array_merge($data,$this->data);
	}
    
	/**
     * 
     * Get current ctl's name(Without 'Controller_') and action's name(Without 'Action'). the ctl is the latest controller's name which was used to call the display function 
     * 
     * @return string
     * 
     * */
    protected function getCtlAndActionName(){
    	$ret['ctl'] = NAME_CONTROLLER;
    	$ret['action'] = NAME_ACTION;
		return $ret;
    }
}
